home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / fog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  11.5 KB  |  378 lines

  1. /* $Id: fog.c,v 1.4 1996/11/04 02:30:15 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.0
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: fog.c,v $
  26.  * Revision 1.4  1996/11/04 02:30:15  brianp
  27.  * optimized gl_fog_color_pixels() and gl_fog_index_pixels()
  28.  *
  29.  * Revision 1.3  1996/09/27 01:26:52  brianp
  30.  * added missing default cases to switches
  31.  *
  32.  * Revision 1.2  1996/09/15 14:17:30  brianp
  33.  * now use GLframebuffer and GLvisual
  34.  *
  35.  * Revision 1.1  1996/09/13 01:38:16  brianp
  36.  * Initial revision
  37.  *
  38.  */
  39.  
  40.  
  41.  
  42. #include <math.h>
  43. #include <stdlib.h>
  44. #include "context.h"
  45. #include "fog.h"
  46. #include "dlist.h"
  47. #include "macros.h"
  48. #include "types.h"
  49.  
  50.  
  51.  
  52. void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
  53. {
  54.    GLenum m;
  55.  
  56.    switch (pname) {
  57.       case GL_FOG_MODE:
  58.          m = (GLenum) (GLint) *params;
  59.      if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
  60.         ctx->Fog.Mode = m;
  61.      }
  62.      else {
  63.         gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  64.      }
  65.      break;
  66.       case GL_FOG_DENSITY:
  67.      if (*params<0.0) {
  68.         gl_error( ctx, GL_INVALID_VALUE, "glFog" );
  69.      }
  70.      else {
  71.         ctx->Fog.Density = *params;
  72.      }
  73.      break;
  74.       case GL_FOG_START:
  75. #ifndef GL_VERSION_1_1
  76.          if (*params<0.0F) {
  77.             gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
  78.             return;
  79.          }
  80. #endif
  81.      ctx->Fog.Start = *params;
  82.      break;
  83.       case GL_FOG_END:
  84. #ifndef GL_VERSION_1_1
  85.          if (*params<0.0F) {
  86.             gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
  87.             return;
  88.          }
  89. #endif
  90.      ctx->Fog.End = *params;
  91.      break;
  92.       case GL_FOG_INDEX:
  93.      ctx->Fog.Index = *params;
  94.      break;
  95.       case GL_FOG_COLOR:
  96.      ctx->Fog.Color[0] = params[0];
  97.      ctx->Fog.Color[1] = params[1];
  98.      ctx->Fog.Color[2] = params[2];
  99.      ctx->Fog.Color[3] = params[3];
  100.          break;
  101.       default:
  102.          gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  103.    }
  104. }
  105.  
  106.  
  107.  
  108.  
  109. /*
  110.  * Compute the fogged color for an array of vertices.
  111.  * Input:  n - number of vertices
  112.  *         v - array of vertices
  113.  *         color - the original vertex colors
  114.  * Output:  color - the fogged colors
  115.  */
  116. void gl_fog_color_vertices( GLcontext *ctx,
  117.                             GLuint n, GLfloat v[][4], GLfixed color[][4] )
  118. {
  119.    GLuint i;
  120.    GLfloat d;
  121.    GLfloat shift = (GLfloat) (1 << ctx->ColorShift);
  122.    GLfloat fogr = ctx->Fog.Color[0] * ctx->Visual->RedScale   * shift;
  123.    GLfloat fogg = ctx->Fog.Color[1] * ctx->Visual->GreenScale * shift;
  124.    GLfloat fogb = ctx->Fog.Color[2] * ctx->Visual->BlueScale  * shift;
  125.    GLfloat foga = ctx->Fog.Color[3] * ctx->Visual->AlphaScale * shift;
  126.    GLfloat end = ctx->Fog.End;
  127.  
  128.    switch (ctx->Fog.Mode) {
  129.       case GL_LINEAR:
  130.          d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  131.          for (i=0;i<n;i++) {
  132.             GLfloat f = (end - ABSF(v[i][2])) * d;
  133.             f = CLAMP( f, 0.0F, 1.0F );
  134.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  135.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  136.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  137.             color[i][3] = f * color[i][3] + (1.0F-f) * foga;
  138.          }
  139.      break;
  140.       case GL_EXP:
  141.          d = -ctx->Fog.Density;
  142.          for (i=0;i<n;i++) {
  143.             GLfloat f = exp( d * ABSF(v[i][2]) );
  144.             f = CLAMP( f, 0.0F, 1.0F );
  145.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  146.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  147.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  148.             color[i][3] = f * color[i][3] + (1.0F-f) * foga;
  149.          }
  150.      break;
  151.       case GL_EXP2:
  152.          d = -(ctx->Fog.Density*ctx->Fog.Density);
  153.          for (i=0;i<n;i++) {
  154.             GLfloat z = ABSF(v[i][2]);
  155.             GLfloat f = exp( d * z*z );
  156.             f = CLAMP( f, 0.0F, 1.0F );
  157.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  158.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  159.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  160.             color[i][3] = f * color[i][3] + (1.0F-f) * foga;
  161.          }
  162.      break;
  163.       default:
  164.          abort();
  165.    }
  166. }
  167.  
  168.  
  169.  
  170. /*
  171.  * Compute the fogged color indexes for an array of vertices.
  172.  * Input:  n - number of vertices
  173.  *         v - array of vertices
  174.  * In/Out: indx - array of vertex color indexes
  175.  */
  176. void gl_fog_index_vertices( GLcontext *ctx,
  177.                             GLuint n, GLfloat v[][4], GLuint indx[] )
  178. {
  179.    /* NOTE: the extensive use of casts generates better/faster code for MIPS */
  180.    switch (ctx->Fog.Mode) {
  181.       case GL_LINEAR:
  182.          {
  183.             GLfloat d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  184.             GLfloat fogindex = ctx->Fog.Index;
  185.             GLfloat fogend = ctx->Fog.End;
  186.             GLuint i;
  187.             for (i=0;i<n;i++) {
  188.                GLfloat f = (fogend - ABSF(v[i][2])) * d;
  189.                f = CLAMP( f, 0.0F, 1.0F );
  190.                indx[i] = (GLint)
  191.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  192.             }
  193.          }
  194.      break;
  195.       case GL_EXP:
  196.          {
  197.             GLfloat d = -ctx->Fog.Density;
  198.             GLfloat fogindex = ctx->Fog.Index;
  199.             GLuint i;
  200.             for (i=0;i<n;i++) {
  201.                GLfloat f = exp( d * ABSF(v[i][2]) );
  202.                f = CLAMP( f, 0.0F, 1.0F );
  203.                indx[i] = (GLint)
  204.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  205.             }
  206.          }
  207.      break;
  208.       case GL_EXP2:
  209.          {
  210.             GLfloat d = -(ctx->Fog.Density*ctx->Fog.Density);
  211.             GLfloat fogindex = ctx->Fog.Index;
  212.             GLuint i;
  213.             for (i=0;i<n;i++) {
  214.                GLfloat z = ABSF(v[i][2]);
  215.                GLfloat f = exp( -d * z*z );
  216.                f = CLAMP( f, 0.0F, 1.0F );
  217.                indx[i] = (GLint)
  218.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  219.             }
  220.          }
  221.      break;
  222.       default:
  223.          abort();
  224.    }
  225. }
  226.  
  227.  
  228.  
  229.  
  230. /*
  231.  * Apply fog to an array of RGBA pixels.
  232.  * Input:  n - number of pixels
  233.  *         z - array of integer depth values
  234.  *         red, green, blue, alpha - pixel colors
  235.  * Output:  red, green, blue, alpha - fogged pixel colors
  236.  */
  237. void gl_fog_color_pixels( GLcontext *ctx,
  238.                           GLuint n, const GLdepth z[], GLubyte red[],
  239.               GLubyte green[], GLubyte blue[], GLubyte alpha[] )
  240. {
  241.    GLfloat c = ctx->ProjectionMatrix[10];
  242.    GLfloat d = ctx->ProjectionMatrix[14];
  243.    GLuint i;
  244.  
  245.    GLfloat fog_red   = ctx->Fog.Color[0] * ctx->Visual->RedScale;
  246.    GLfloat fog_green = ctx->Fog.Color[1] * ctx->Visual->GreenScale;
  247.    GLfloat fog_blue  = ctx->Fog.Color[2] * ctx->Visual->BlueScale;
  248.    GLfloat fog_alpha = ctx->Fog.Color[3] * ctx->Visual->AlphaScale;
  249.  
  250.    GLfloat tz = ctx->Viewport.Tz;
  251.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  252.  
  253.    switch (ctx->Fog.Mode) {
  254.       case GL_LINEAR:
  255.          {
  256.             GLfloat fogEnd = ctx->Fog.End;
  257.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  258.             for (i=0;i<n;i++) {
  259.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  260.                GLfloat eyez = -d / (c+ndcz);
  261.                GLfloat f, g;
  262.                if (eyez < 0.0)  eyez = -eyez;
  263.                f = (fogEnd - eyez) * fogScale;
  264.                f = CLAMP( f, 0.0F, 1.0F );
  265.                g = 1.0F - f;
  266.                red[i]   = (GLint) (f * (GLfloat) red[i]   + g * fog_red);
  267.                green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
  268.                blue[i]  = (GLint) (f * (GLfloat) blue[i]  + g * fog_blue);
  269.                alpha[i] = (GLint) (f * (GLfloat) alpha[i] + g * fog_alpha);
  270.             }
  271.          }
  272.      break;
  273.       case GL_EXP:
  274.      for (i=0;i<n;i++) {
  275.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  276.         GLfloat eyez = -d / (c+ndcz);
  277.             GLfloat f, g;
  278.         if (eyez < 0.0)  eyez = -eyez;
  279.         f = exp( -ctx->Fog.Density * eyez );
  280.         f = CLAMP( f, 0.0F, 1.0F );
  281.             g = 1.0F - f;
  282.             red[i]   = (GLint) (f * (GLfloat) red[i]   + g * fog_red);
  283.             green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
  284.             blue[i]  = (GLint) (f * (GLfloat) blue[i]  + g * fog_blue);
  285.             alpha[i] = (GLint) (f * (GLfloat) alpha[i] + g * fog_alpha);
  286.      }
  287.      break;
  288.       case GL_EXP2:
  289.          {
  290.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  291.             for (i=0;i<n;i++) {
  292.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  293.                GLfloat eyez = -d / (c+ndcz);
  294.                GLfloat f, g;
  295.                if (eyez < 0.0)  eyez = -eyez;
  296.                f = exp( negDensitySquared * eyez*eyez );
  297.                f = CLAMP( f, 0.0F, 1.0F );
  298.                g = 1.0F - f;
  299.                red[i]   = (GLint) (f * (GLfloat) red[i]   + g * fog_red);
  300.                green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
  301.                blue[i]  = (GLint) (f * (GLfloat) blue[i]  + g * fog_blue);
  302.                alpha[i] = (GLint) (f * (GLfloat) alpha[i] + g * fog_alpha);
  303.             }
  304.          }
  305.      break;
  306.       default:
  307.          abort();
  308.    }
  309. }
  310.  
  311.  
  312.  
  313.  
  314. /*
  315.  * Apply fog to an array of color index pixels.
  316.  * Input:  n - number of pixels
  317.  *         z - array of integer depth values
  318.  *         index - pixel color indexes
  319.  * Output:  index - fogged pixel color indexes
  320.  */
  321. void gl_fog_index_pixels( GLcontext *ctx,
  322.                           GLuint n, const GLdepth z[], GLuint index[] )
  323. {
  324.    GLfloat c = ctx->ProjectionMatrix[10];
  325.    GLfloat d = ctx->ProjectionMatrix[14];
  326.    GLuint i;
  327.  
  328.    GLfloat tz = ctx->Viewport.Tz;
  329.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  330.  
  331.    switch (ctx->Fog.Mode) {
  332.       case GL_LINEAR:
  333.          {
  334.             GLfloat fogEnd = ctx->Fog.End;
  335.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  336.             for (i=0;i<n;i++) {
  337.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  338.                GLfloat eyez = -d / (c+ndcz);
  339.                GLfloat f;
  340.                if (eyez < 0.0)  eyez = -eyez;
  341.                f = (fogEnd - eyez) * fogScale;
  342.                f = CLAMP( f, 0.0F, 1.0F );
  343.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  344.             }
  345.      }
  346.      break;
  347.       case GL_EXP:
  348.          for (i=0;i<n;i++) {
  349.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  350.         GLfloat eyez = -d / (c+ndcz);
  351.             GLfloat f;
  352.         if (eyez < 0.0)  eyez = -eyez;
  353.         f = exp( -ctx->Fog.Density * eyez );
  354.         f = CLAMP( f, 0.0F, 1.0F );
  355.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  356.      }
  357.      break;
  358.       case GL_EXP2:
  359.          {
  360.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  361.             for (i=0;i<n;i++) {
  362.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  363.                GLfloat eyez = -d / (c+ndcz);
  364.                GLfloat f;
  365.                if (eyez < 0.0)  eyez = -eyez;
  366.                f = exp( negDensitySquared * eyez*eyez );
  367.                f = CLAMP( f, 0.0F, 1.0F );
  368.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  369.             }
  370.      }
  371.      break;
  372.       default:
  373.          abort();
  374.    }
  375.  
  376. }
  377.  
  378.